#region Usings
using System;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Diagnostics;
using System.Globalization;
using System.Deployment.Application;
using System.IO;
using System.Collections;
using System.Net;
#endregion

namespace TexasHoldEmCroupier.ApplicationController
{
    public partial class Controller : IDisposable
    {
        #region Constants
        private const long LONG_ZERO = 0;
        #endregion

        #region Properties
        public static string BuildVersion
        {
            get
            {
                if (File.Exists(Application.StartupPath + "\\SVNBuildInfo.txt"))
                {
                    string[] theLogLines = 
                        File.ReadAllLines(Application.StartupPath + "\\SVNBuildInfo.txt");

                    if (theLogLines.Length > 1)
                    {
                        return theLogLines[1].Substring(1, 4).Trim();
                    }
                }
                return "Not Available";
            }
        }

        public static string PublishVersion
        {
            get
            {
                if (ApplicationDeployment.IsNetworkDeployed)
                {
                    ApplicationDeployment ad =
                        ApplicationDeployment.CurrentDeployment;

                    return String.Format(
                        CultureInfo.CurrentCulture,
                        "{0}.{1}.{2}.{3}",
                        ad.CurrentVersion.Major,
                        ad.CurrentVersion.Minor,
                        ad.CurrentVersion.Build,
                        ad.CurrentVersion.Revision);
                }
                return "Not Deployed";
            }
        }
        #endregion

        #region Members
        private ApplicationContext _AppContext;
        private IntPtr _NativeResource;
        #endregion

        #region Methods
        /// <summary>
        /// Start controlling the application
        /// </summary>
        public void StartApp()
        {
            this._NativeResource = Marshal.AllocHGlobal(100);

            // Enable XP styles
            Application.EnableVisualStyles();

            Application.SetCompatibleTextRenderingDefault(false);

            // Setup unhandled exception handlers
            AppDomain.CurrentDomain.UnhandledException += // CLR
               new UnhandledExceptionEventHandler(OnUnhandledException);
            Application.ThreadException += // Windows Forms
                new ThreadExceptionEventHandler(OnGuiUnhandedException);

            // Create an Application Context
            this._AppContext = new ApplicationContext();

            // Start by showing the main application screen
            this.MainView_Show();

            if (!this._MainView.IsDisposed)
            {
                // Single instance checked
                bool IsFirstInstance;
                Mutex theMutex = new Mutex(false, "Local\\TexasHoldEmCroupier", out IsFirstInstance);

                /* If IsFirstInstance is now true, we're the first instance of the application; 
                 * otherwise another instance is running.
                 */
                if (IsFirstInstance)
                {
                    Application.Run(this._AppContext);
                }
                theMutex.Close();
                Application.Exit();
            }
        }

        #region Handle Exceptions
        // CLR unhandled exception
        private void OnUnhandledException(
            Object sender, UnhandledExceptionEventArgs e)
        {
            this._MainView.Cursor =
                Cursors.Default;

            HandleUnhandledException(e.ExceptionObject);
        }

        // Windows Forms unhandled exception
        private void OnGuiUnhandedException(
            Object sender, ThreadExceptionEventArgs e)
        {
            if (null != this._MainView)
            {
                this._MainView.Cursor =
                    Cursors.Default;
            }
            
            if (!e.Exception.GetType().Equals(typeof(IndexOutOfRangeException)))
            {
                HandleUnhandledException(e.Exception);
            }
        }

        /// <summary>
        /// Handle the Application_ThreadException event
        /// </summary>
        /// <param name="sender">Application</param>
        /// <param name="e">ThreadExceptionEventArgs</param>
        private static void HandleUnhandledException(Object sender)
        {
            Exception theException =
                sender as Exception;

            if (theException.GetType().Equals(typeof(FileNotFoundException)))
            {
                switch (MessageBox.Show(
                    "One or more components that the application requires appears to be missing\n\n" +
                    "If this error persists, please contact Computa Services & Consultants\n\n" +
                    "Would you like the application to re-check the prerequisites now?",
                    "Missing Components",
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Stop,
                    MessageBoxDefaultButton.Button1))
                {
                    case DialogResult.No:
                        Application.DoEvents();
                        return;
                }

                Application.DoEvents();

                Process.Start(@"http://software.computa.co.uk/aspnet/CarnoustieGolfLinks/OnlineBookingManager/setup.exe");

                Application.Exit();
            }
            else
            {
                EventLog theApplicationLog = new EventLog();
                theApplicationLog.Source = "CGL Online Manager";
                theApplicationLog.WriteEntry(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        "Exception: {0}",
                        theException.Message
                    ),
                    EventLogEntryType.Error);

                MessageBox.Show(
                    "An error report has been written to the Event Log\n\n"
                        + "Please inform Computa Services & Consultants",
                    "Error Occurred",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Stop,
                    MessageBoxDefaultButton.Button1);
            }

            Application.DoEvents();
        }
        #endregion

        #region IDisposable Members
        // Dispose() calls Dispose(true)
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        // NOTE: Leave out the finalizer altogether if this class doesn't 
        // own unmanaged resources itself, but leave the other methods
        // exactly as they are. 
        ~Controller()
        {
            // Finalizer calls Dispose(false)
            Dispose(false);
        }
        // The bulk of the clean-up code is implemented in Dispose(bool)
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // free managed resources
                if (_MainView != null)
                {
                    _MainView.Dispose();
                    _MainView = null;
                }
                if (_AppContext != null)
                {
                    _AppContext.Dispose();
                    _AppContext = null;
                }
            }
            // free native resources if there are any.
            if (_NativeResource != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(_NativeResource);
                _NativeResource = IntPtr.Zero;
            }
        }
        #endregion

        #region Helper Methods
        private static Form GetOwnerForm(ToolStripItem menuItem)
        {
            if (menuItem == null) return null;

            if (menuItem.Owner is ContextMenuStrip)
            {
                ContextMenuStrip contextMenuStrip = (ContextMenuStrip)menuItem.Owner;

                // Get the Control that initiated the context menu
                Control control = contextMenuStrip.SourceControl;

                // Temporary hack.  There is a bug in WinForms where the SourceControl
                // property is not set properly when the menu item that initiated the
                // click event is located within a sub-menu.  If this is the case,
                // the Form can be retrieved from the Tag property of the ContextMenuStrip
                if (control == null)
                {
                    return contextMenuStrip.Tag as Form;
                }

                return control.FindForm();
            }
            else if (menuItem.Owner is ToolStripDropDown)
            {
                // Sub Level item, so recurse to find the parent
                ToolStripDropDown dropDownMenu = (ToolStripDropDown)menuItem.Owner;
                return GetOwnerForm(dropDownMenu.OwnerItem);
            }
            else if (menuItem.Owner is ToolStrip)
            {
                ToolStrip toolStrip = (ToolStrip)menuItem.Owner;
                return toolStrip.FindForm();
            }
            else
            {
                return null;
            }
        }

        private static Form GetOwnerForm(object theObject)
        {
            if (theObject is Control)
            {
                Control theControl =
                    theObject as Control;

                return theControl.FindForm();
            }
            else
            {
                ToolStripItem theToolStripItem =
                    theObject as ToolStripItem;

                return GetOwnerForm(theToolStripItem);
            }
        }

        private static Image GetImageFromURL(string strURL)
        {
            HttpWebRequest theRequest = 
                (HttpWebRequest)HttpWebRequest.Create(strURL);
            theRequest.Timeout = 5000; // 5 seconds in milliseconds
            theRequest.ReadWriteTimeout = 20000; // allow up to 20 seconds to elapse

            HttpWebResponse theResponse = 
                (HttpWebResponse)theRequest.GetResponse();

            return Image.FromStream(theResponse.GetResponseStream());
        }
        #endregion

        #region Refresh All
        private void RefreshAll(Type theViewType)
        {
            foreach (Form thisView in this._MainView.MdiChildren)
            {
                if (thisView.GetType().Equals(theViewType))
                {
                }
            }
        }
        #endregion
        #endregion
    }
}
